package com.wangke.test.container;

import java.util.LinkedList;

/**
 * @author wangke
 * @version v1.0
 * @项目名称: study
 * @描述:
 * 写一个固定容量同步容器，拥有put和get方法，以及getCount方法，能够支持多个生产者和多个消费者线程拥塞调用。
 *
 * 1.使用synchronized锁或ReentrantLock锁实现
 *
 * 1）使用synchronized锁的notify、notifyAll来实现
 *
 * 基本思路：使用put方法向容器中添加元素，使用get方法从容器中取出元素，
 * 在使用put方法添加元素的时候进行判断，
 * 如果容器已经满了，此时调用wait()方法，使用添加线程阻塞，等待消费线程取出元素，
 * 腾出容器空间后才能再向其中添加元素，
 * 同理当使用get方法获取元素的时候，如果同期已经为空，此时要调用wait()方法，使得取出线程阻塞，等待添加线程添加元素，
 * 容器有值后才能再从容器中取出元素。
 * @创建时间: 2019/4/26
 * @update [序号][日期YYYY-MM-DD] [更改人姓名][变更描述]
 */
public class MyContainer1<T> {
     final private LinkedList<T> lists = new LinkedList<>();
     private final int MAX = 10;
     private int count = 0;

     public synchronized void put(T t){
        while (lists.size()==MAX){
            try{
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
         lists.add(t);
         ++count;
         System.out.println("容器中的数量=="+count);
         this.notifyAll();//通知所有消费者消费
     }



     /*
        get ,消费
      */
    public synchronized T get(){
        T t = null;
        while (lists.size()==0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        t = lists.removeFirst();
        count--;
        System.out.println("消费者容器数量="+count);
        this.notifyAll();
        return t;

    }


    public static void main(String[] args) {
        MyContainer1<String> c = new MyContainer1<>();

        //启动生产者线程 2个线程，每个生产25次
        for (int i = 0; i < 2; i++) {

            new Thread(()->{
                for (int j = 0; j < 25; j++) {
                    c.put(Thread.currentThread().getName()+j);
                }
            },"生产"+i).start();

        }

        //sleep两秒
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //启动消费者
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                for (int j = 0; j <5 ; j++) {
                    c.get();
                }
            },"thread"+i).start();
        }





        
        


    }



}
